﻿// -----------------------------------------------------------------------
// <copyright file="PluralizerTest.cs" company="Moveax, LLC">
// Copyright (c) 2013 Andrey Veselov. All rights reserved.
// License:  Microsoft Public License (MS-PL)
// Contacts: http://andrey.moveax.com andrey@moveax.com
// </copyright>
// -----------------------------------------------------------------------

namespace Moveax.Pluralization.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Moveax.Pluralization.Core;

    [TestClass]
    public class PluralizerTest
    {
        [TestMethod]
        public void GetDefaultPluralizerForUnknownCulture()
        {
            // Arrange
            const PluralCategory expectedForInt = PluralCategory.One;
            const PluralCategory expectedForFloat = PluralCategory.Other;
            var rules = new PluralRulesFactory().Create(new CultureInfo("yo-NG"));

            // Act
            // calls should return "en" values for unsupported culture
            var actualForInt = rules.GetCategoryFor(1);
            var actualForFloat = rules.GetCategoryFor(1.3f);

            // Assert
            Assert.AreEqual(expectedForInt, actualForInt);
            Assert.AreEqual(expectedForFloat, actualForFloat);
        }

        [TestMethod]
        public void ValudateRules_Western()
        {
            var codes = new string[] { "en-US", "de-DE", "it-IT", "es-ES", "pt-PT" };

            foreach (var code in codes) {
                // Arrange
                string expectedLanguageCode = code.Substring(0, 2).ToLower();
                var rules = new PluralRulesFactory().Create(new CultureInfo(code));
                var values = new Tuple<float, PluralCategory>[] {
                    new Tuple<float,PluralCategory>(0.0f, PluralCategory.Other),
                    new Tuple<float,PluralCategory>(1.0f, PluralCategory.One),
                    new Tuple<float,PluralCategory>(2.0f, PluralCategory.Other),
                    new Tuple<float,PluralCategory>(3.5f, PluralCategory.Other)
                };

                // Act & Assert
                this.TestRules(rules, values, expectedLanguageCode);
            }
        }

        [TestMethod]
        public void ValudateWesternRules_Slavic()
        {
            var codes = new string[] { "ru-RU", "uk-UA", "be-BY" };

            foreach (var code in codes) {
                // Arrange
                string expectedLanguageCode = code.Substring(0, 2).ToLower();

                var rules = new PluralRulesFactory().Create(new CultureInfo(code));
                var values = new Tuple<float, PluralCategory>[] {
                    new Tuple<float,PluralCategory>(0.0f, PluralCategory.Many),
                    new Tuple<float,PluralCategory>(1.0f, PluralCategory.One),
                    new Tuple<float,PluralCategory>(2.0f, PluralCategory.Few),
                    new Tuple<float,PluralCategory>(5.4f, PluralCategory.Other)
                };

                // Act & Assert
                this.TestRules(rules, values, expectedLanguageCode);
            }
        }

        [TestMethod]
        public void ValudateRules_Fr()
        {
            // Arrange
            const string expectedLanguageCode = "fr";
            var rules = new PluralRulesFactory().Create(new CultureInfo("fr-FR"));
            var values = new Tuple<float, PluralCategory>[] {
                new Tuple<float,PluralCategory>(0.0f, PluralCategory.One),
                new Tuple<float,PluralCategory>(1.3f, PluralCategory.One),
                new Tuple<float,PluralCategory>(2.0f, PluralCategory.Other),
                new Tuple<float,PluralCategory>(5.0f, PluralCategory.Other),
                new Tuple<float,PluralCategory>(8.4f, PluralCategory.Other)
            };

            // Act & Assert
            this.TestRules(rules, values, expectedLanguageCode);
        }

        private void TestRules(IPluralRules rules, Tuple<float, PluralCategory>[] values, string expectedLanguageCode)
        {
            // Arrange
            var count = values.Count();
            var actual = new List<PluralCategory>();
            var expected = new List<PluralCategory>();

            // Act
            foreach (var value in values) {
                var floatValue = value.Item1;

                if ((floatValue % 1).Equals(0)) { // is integer
                    var intValue = (int)floatValue;
                    actual.Add(rules.GetCategoryFor(intValue));
                    expected.Add(value.Item2);

                    actual.Add(rules.GetCategoryFor(-intValue));
                    expected.Add(value.Item2);
                }


                actual.Add(rules.GetCategoryFor(floatValue));
                expected.Add(value.Item2);

                actual.Add(rules.GetCategoryFor(-floatValue));
                expected.Add(value.Item2);
            }

            // Assert
            Assert.AreEqual(rules.LanguageCode, expectedLanguageCode);

            for (var i = 0; i < count; i++)
                Assert.AreEqual(expected[i], actual[i]);
        }
    }
}